﻿using Basic.IdGenerator;
using Basic.Repository.Abstract.Entities;
using Basic.Repository.Abstract.IRepositories;
using Basic.Repository.Abstract.Transactions;
using Basic.Repository.SqlSugar;
using Basic.Repository.SqlSugar.UnitOfWork;
using Microsoft.Extensions.Configuration;
using System.Linq.Dynamic.Core;

namespace Microsoft.Extensions.DependencyInjection;

/// <summary>
/// SqlSugar 
/// </summary>
public static class ServiceCollectionExtension
{
    public static IServiceCollection AddSqlsugarSetup(this IServiceCollection services, IConfigurationSection dbSection)
    {
        if (services == null)
            throw new ArgumentNullException(nameof(services));

        DBConfig dbConfig = dbSection.Get<DBConfig>();
        var mainDb = dbConfig.MainDb;
        #region 数据库连接对象
        // 连接字符串
        var listConfig = new List<ConnectionConfig>();
        // 从库
        var listConfig_Slave = new List<SlaveConnectionConfig>();
        BaseDBConfig.dbConfig = dbConfig;
        BaseDBConfig.MutiConnectionString.slaveDbs.ForEach(s =>
        {
            listConfig_Slave.Add(new SlaveConnectionConfig
            {
                HitRate = s.HitRate,
                ConnectionString = s.Connection
            });
        });

        BaseDBConfig.MutiConnectionString.allDbs.ForEach(m =>
        {
            listConfig.Add(new ConnectionConfig()
            {
                ConfigId = m.ConnId.ToString().ToLower(),
                ConnectionString = m.Connection,
                DbType = m.DbType,
                IsAutoCloseConnection = true,
                AopEvents = new AopEvents
                {
                    OnLogExecuting = (sql, p) =>
                    {
                        if (dbConfig.SqlAOP)
                        {
                            if (sql.StartsWith("SELECT"))
                                Console.ForegroundColor = ConsoleColor.Green;
                            if (sql.StartsWith("INSERT"))
                                Console.ForegroundColor = ConsoleColor.White;
                            if (sql.StartsWith("DELETE"))
                                Console.ForegroundColor = ConsoleColor.Red;
                            Console.WriteLine($"-----{DateTime.Now:yyyy-MM-dd HH:mm:ss}-----\r\n{sql}" +
                                $"【参数】\r\n{GetParas(p)}");
                        }
                    },
                    DataExecuting = (oldValue, entiy) =>
                    {
                        if (entiy.OperationType == DataFilterType.InsertByObject)
                        {
                            if (entiy.PropertyName == "Id")
                            {
                                if (oldValue.ObjectIsNullOrZero()) entiy.SetValue(IdGenerator.NewId());
                            }

                            //if (entiy.PropertyName == "CreationTime")
                            //    entiy.SetValue(DateTime.Now);
                            //if (entiy.PropertyName == "CreateBy") 
                        }
                        //由AuditInterceptor处理
                        //if (entiy.OperationType == DataFilterType.UpdateByObject)
                        //{
                        //    if (entiy.PropertyName == "ModifiedBy")
                        //    {
                        //    }
                        //    if (entiy.PropertyName == "ModificationTime")
                        //        entiy.SetValue(DateTime.Now);
                        //}
                    }
                    ,
                },
                MoreSettings = new ConnMoreSettings()
                {
                    //IsWithNoLockQuery = true,
                    IsAutoRemoveDataCache = true
                },
                // 从库
                SlaveConnectionConfigs = listConfig_Slave,
                // 自定义特性
                ConfigureExternalServices = new ConfigureExternalServices()
                {
                    // DataInfoCacheService = new SqlSugarMemoryCacheService(memoryCache),
                    EntityService = (property, column) =>
                    {
                        if (column.IsPrimarykey && property.PropertyType == typeof(int))
                        {
                            column.IsIdentity = true;
                        }
                    }
                    //EntityNameService = (type, entity) => { entity.DbTableName = }
                },
                InitKeyType = InitKeyType.Attribute
            }
           );
        });
        #endregion
        services.AddRepository();
        services.AddSingleton(listConfig);
        services.AddSingleton<ISqlSugarClient>(o =>
        {
            return new SqlSugarScope(listConfig, db =>
            {
                //db.SetDataFilter();
            });
        });

        return services;
    }

    private static IServiceCollection AddRepository(this IServiceCollection services)
    {
        services.AddTransient<IUnitOfWorkManage, UnitOfWorkManage>();
        services.AddTransient(typeof(IBaseRepository<>), typeof(BaseRepository<>));
        return services;
    }

    private static string GetParas(SugarParameter[] pars)
    {
        string key = "【SQL参数】：";
        foreach (var param in pars)
        {
            key += $"{param.ParameterName}:{param.Value}\n";
        }

        return key;
    }
    public static void SetDataFilter(this ISqlSugarClient db, List<long> dataScopeIdList, Assembly assembly)
    {
        var types = assembly.GetTypes();
        types = types.Where(u =>
              typeof(IEntity).IsAssignableFrom(u)).ToArray();
        foreach (var item in types)
        {
            var param = Expression.Parameter(item, "a");
            var expression = DynamicExpressionParser.ParseLambda(
                new[] { param }, typeof(bool), $"CreatBy in @0", dataScopeIdList);
            //db.QueryFilter.AddTableFilter<IEntity>(expression);//多租户写法
            db.QueryFilter.AddTableFilter(item, expression);
        }
    }

    /// <summary>
    /// 字段创建视图拓展
    /// </summary>
    /// <param name="client"></param>
    /// <param name="views"></param>
    public static void InitViews(this ISqlSugarClient client, DbType dbType, params IView[] views)
    {
        foreach (IView view in views)
        {
            string viewName = view.GetType().Name;
            if (dbType == DbType.PostgreSQL || dbType == DbType.MySql)
                viewName = viewName.ToLower();

            string queryViewFormat = @"select table_name from information_schema.views where table_name = '{0}'";
            string queryViewSql = string.Format(queryViewFormat, viewName);

            string dbResult = client.Ado.SqlQuerySingle<string>(queryViewSql);
            if (dbResult != null)
                continue;

            string createViewFormat = @"CREATE VIEW [{0}] AS {1}";
            string createViewSql = string.Format(createViewFormat, viewName, view.ViewSql());

            if (dbType == DbType.PostgreSQL || dbType == DbType.MySql)
            {
                createViewSql = createViewSql.Replace('[', '"');
                createViewSql = createViewSql.Replace(']', '"');
                createViewSql = createViewSql.ToLower();
            }
            client.Ado.ExecuteCommand(createViewSql);
        }
    }

}